package com.stellar.pay.core.utils;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;


/**
 * @Author Jqcc
 * @Version 1.0
 * @Data 2025/4/4
 * @Description : 幂等请求检测工具类 - 单机部署使用内存版
 * @see RedisIdempotentRequestChecker -  集群环境使用Redis版
 */
public class IdempotentRequestChecker {

    // 请求记录缓存，使用ConcurrentHashMap保证线程安全
    private static final Map<String, RequestRecord> REQUEST_CACHE = new ConcurrentHashMap<>();

    // 默认请求有效时间（毫秒）
    private static final long DEFAULT_EXPIRE_TIME = TimeUnit.MINUTES.toMillis(5);

    /**
     * 检查是否为重复请求
     *
     * @param key 请求唯一标识（如orderNo）
     * @return true-是重复请求，false-不是重复请求
     */
    public static boolean isDuplicateRequest(String key) {
        return isDuplicateRequest(key, DEFAULT_EXPIRE_TIME);
    }

    /**
     * 检查是否为重复请求
     *
     * @param key        请求唯一标识
     * @param expireTime 请求有效时间（毫秒）
     * @return true-是重复请求，false-不是重复请求
     */
    public static boolean isDuplicateRequest(String key, long expireTime) {
        RequestRecord record = REQUEST_CACHE.get(key);
        long currentTime = System.currentTimeMillis();

        if (record != null) {
            // 检查是否在有效期内
            if (currentTime - record.getTimestamp() < expireTime) {
                return true;
            }
        }

        // 更新或添加新记录
        REQUEST_CACHE.put(key, new RequestRecord(currentTime));
        return false;
    }

    /**
     * 清除指定key的请求记录
     *
     * @param key 请求唯一标识
     */
    public static void clearRequest(String key) {
        REQUEST_CACHE.remove(key);
    }

    /**
     * 清除所有过期的请求记录
     *
     * @param expireTime 过期时间（毫秒）
     */
    public static void clearExpiredRequests(long expireTime) {
        long currentTime = System.currentTimeMillis();
        REQUEST_CACHE.entrySet().removeIf(entry ->
                currentTime - entry.getValue().getTimestamp() >= expireTime
        );
    }

    // 请求记录内部类
    private static class RequestRecord {
        private final long timestamp;

        public RequestRecord(long timestamp) {
            this.timestamp = timestamp;
        }

        public long getTimestamp() {
            return timestamp;
        }
    }
}